home *** CD-ROM | disk | FTP | other *** search
/ Palm Utilities / Palm_Utilities_CD-ROM_2001_2001.iso / files / misc / PalmMOD 1.1 / palmm11.exe / MKMOTD.C next >
Encoding:
C/C++ Source or Header  |  1998-07-18  |  11.7 KB  |  345 lines

  1. /****************************************************************************
  2. *
  3. * FILE:         mkmotd.c
  4. *
  5. * PURPOSE:      Make a message-of-the-day database
  6. *
  7. * DESCRIPTION:  A message-of-the-day database has a specific format that
  8. *               must be followed so that all programs that use the data
  9. *               can use it correctly.
  10. *
  11. *               Most of the records in the database are simply null-
  12. *               terminated text strings that contain messages, one per
  13. *               record. The database's first record is special, and contains
  14. *               the following information:
  15. *
  16. *               mode (4 bytes, unsigned) - this field describes how the
  17. *                 text records in the rest of the database are used:
  18. *
  19. *                 mode = 1: only the first text record is used, and it is
  20. *                           used over and over again. PalmJournal can use
  21. *                           this mode to insert a standard text template
  22. *                           into every day's new journal entry.
  23. *                 mode = 2: each record is used in turn, starting with the
  24. *                           first text record. This is useful for a message
  25. *                           of the day, where the particular day doesn't
  26. *                           matter. The most recently-used record's index
  27. *                           can be stored in the last_used field (below)
  28. *                           to keep things in order. When the last record
  29. *                           has been used, the program starts over again
  30. *                           at the first record.
  31. *                 mode = 3: only the first 7 records are used, based on the
  32. *                           day of the week.  The first record is for Sunday,
  33. *                           the second for Monday, etc. PalmJournal can use
  34. *                           this mode to provide a different text template
  35. *                           for each weekday's journal entry.
  36. *                 mode = 4: there must be at least 366 records for this mode.
  37. *                           Each record corresponds to a day of the year.
  38. *                           **NOTE: Feruary 29 is treated specially... it's
  39. *                           always the 366th day. This way, each day's number
  40. *                           within the year is constant, regardless of leap
  41. *                           year.
  42. *
  43. *               last_used (2 bytes, unsigned) - this field is really only
  44. *                 useful for mode 2, since the other modes always determine
  45. *                 which record number to use by some other method. Only mode
  46. *                 2 requires the program to remember which record was used
  47. *                 last.
  48. *
  49. *               This program takes a single command-line argument: the mode
  50. *               number for the resulting database (see above).
  51. *
  52. *               This program reads the input file "motddb.txt" (in the
  53. *               current directory) as the source of the text records for the
  54. *               database. Each record in the file must be on a single line,
  55. *               and empty lines are not allowed. Records may include linefeeds
  56. *               as "\n" in the text.
  57. *
  58. *               This program creates the file "motddb.pdb" in the current
  59. *               directory. This program also assumes that it is being run
  60. *               on an INTEL-like processor, and so will byte-swap short and
  61. *               long integers. Just change the SSwap and LSwap routines if
  62. *               you compile this on some other architecture.
  63. *
  64. * REVISION HISTORY:
  65. *   v 1.0   Original release
  66. *   v 1.1   Increased maximum line length to 4096, fixed international
  67. *           character compatibility, added command-line parameters
  68. ****************************************************************************/
  69. #include <stdio.h>
  70. #include <stdlib.h>
  71. #include <string.h>
  72.  
  73. #define TRUE 1
  74. #define FALSE 0
  75.  
  76. /* this is a PALM OS standard -- do not change */
  77. #define DB_NAME_SIZE 32
  78.  
  79. /* this is an arbitrary number, make it whatever you want */
  80. #define MAX_RECORDS 400
  81.  
  82. /* again, an arbitrary number, for convenient programming */
  83. #define MAX_LINE_LENGTH 4096
  84.  
  85. /* the linefeed character */
  86. #define LF 0x0a
  87.  
  88. /* the file names */
  89. char *outfile_name = "motddb.pdb";
  90. char *infile_name = "motddb.txt";
  91.  
  92. /* there shouldn't be any need to change these initial values */
  93. char db_name[DB_NAME_SIZE];
  94. unsigned short db_attributes = 0;
  95. unsigned short db_version = 0;
  96. unsigned long db_creation_date = 0x32cb1cc2;
  97. unsigned long db_modification_date = 0x32cb1cc2;
  98. unsigned long db_last_backup_date = 0x32cb1cc2;
  99. unsigned long db_modification_number = 1;
  100. unsigned long db_app_info_id = 0;
  101. unsigned long db_sort_info_id = 0;
  102. unsigned char db_type[4] = {'D', 'a', 't', 'a'};
  103. unsigned char db_creator[4] = {'C', 'k', 's', '4'};
  104. unsigned long db_unique_id_seed = 0;
  105. unsigned long db_next_record_list_id = 0;
  106. unsigned short db_num_records = 0;
  107.  
  108. unsigned char rec_attributes = 0;
  109.  
  110. /* this is a pointer to the buffer that holds the records when they are
  111.    read in */
  112. char *record[MAX_RECORDS];
  113.  
  114. /* local function prototypes */
  115. long get_records(void);
  116. unsigned long LSwap(unsigned long l);
  117. unsigned short SSwap(unsigned short s);
  118. char *transform(char *s);
  119.  
  120. /***************************************************************************
  121. * main()
  122. ***************************************************************************/
  123. main(int argc, char * argv[]) {
  124. FILE *outfile;
  125. unsigned long mode = 2;
  126. unsigned short last_used = 0;
  127. unsigned short i;
  128. long pad = 0;
  129. unsigned long  offset = 80;
  130. unsigned char   temp_char;
  131. unsigned short temp_short;
  132. unsigned long  temp_long;
  133.  
  134. for (i = 1; i < argc; i++) {
  135.   if (argv[i][0] == '-') {
  136.     switch (argv[i][1]) {
  137.       case 'm':
  138.         if (argc > (i + 1))
  139.           mode = atol(argv[i + 1]);
  140.         break;
  141.       case 'i':
  142.         if (argc > (i + 1))
  143.           infile_name = argv[i + 1];
  144.         break;
  145.       case 'o':
  146.         if (argc > (i + 1))
  147.           outfile_name = argv[i + 1];
  148.         break;
  149.       default:
  150.         printf("usage: mkmotd [-m mode] [-i input file] [-o output file]\n");
  151.         printf("       default mode is 2\n");
  152.         printf("       default input file is motddb.txt\n");
  153.         printf("       default output file is motddb.pdb\n");
  154.         return(1);
  155.         break;
  156.     }
  157.   }
  158. }
  159.  
  160. printf("mkmotd: mode = %ld\ninput file = %s\noutput file = %s\n", mode, infile_name, outfile_name);
  161.  
  162. outfile = fopen(outfile_name, "wb");
  163. if (outfile) {
  164.  
  165.   memset(db_name, 0, DB_NAME_SIZE);
  166.   strcpy(db_name, "MOTDDB");
  167.   fwrite(db_name, DB_NAME_SIZE, 1, outfile);
  168.  
  169.   temp_short = SSwap(db_attributes);
  170.   fwrite(&temp_short, sizeof(temp_short), 1, outfile);
  171.  
  172.   temp_short = SSwap(db_version);
  173.   fwrite(&temp_short, sizeof(temp_short), 1, outfile);
  174.  
  175.   temp_long = LSwap(db_creation_date);
  176.   fwrite(&temp_long, sizeof(temp_long), 1, outfile);
  177.  
  178.   temp_long = LSwap(db_modification_date);
  179.   fwrite(&temp_long, sizeof(temp_long), 1, outfile);
  180.  
  181.   temp_long = LSwap(db_last_backup_date);
  182.   fwrite(&temp_long, sizeof(temp_long), 1, outfile);
  183.  
  184.   temp_long = LSwap(db_modification_number);
  185.   fwrite(&temp_long, sizeof(temp_long), 1, outfile);
  186.  
  187.   temp_long = LSwap(db_app_info_id);
  188.   fwrite(&temp_long, sizeof(temp_long), 1, outfile);
  189.  
  190.   temp_long = LSwap(db_sort_info_id);
  191.   fwrite(&temp_long, sizeof(temp_long), 1, outfile);
  192.  
  193.   fwrite(&db_type, 4, 1, outfile);
  194.   fwrite(&db_creator, 4, 1, outfile);
  195.  
  196.   temp_long = LSwap(db_unique_id_seed);
  197.   fwrite(&temp_long, sizeof(temp_long), 1, outfile);
  198.  
  199.   temp_long = LSwap(db_next_record_list_id);
  200.   fwrite(&temp_long, sizeof(temp_long), 1, outfile);
  201.   
  202.   db_num_records = get_records() + 1;
  203.   temp_short = SSwap(db_num_records);
  204.   fwrite(&temp_short, sizeof(temp_short), 1, outfile);
  205.  
  206.   offset += (db_num_records * 8);
  207.  
  208. /* write the record index for the special first record */
  209.   temp_long = LSwap(offset);
  210.   fwrite(&temp_long, sizeof(temp_long), 1, outfile);
  211.   fwrite(&rec_attributes, sizeof(rec_attributes), 1, outfile);
  212.   temp_char = 20;
  213.   fwrite(&temp_char, sizeof(temp_char), 1, outfile);
  214.   temp_char = 0;
  215.   fwrite(&temp_char, sizeof(temp_char), 1, outfile);
  216.   temp_char = 0;
  217.   fwrite(&temp_char, sizeof(temp_char), 1, outfile);
  218.   offset += 6;
  219.  
  220. /* write the record indeces for the text records */
  221.   for (i = 0; i < db_num_records - 1; i++) {
  222.     temp_long = LSwap(offset);
  223.     fwrite(&temp_long, sizeof(temp_long), 1, outfile);
  224.     fwrite(&rec_attributes, sizeof(rec_attributes), 1, outfile);
  225.     temp_char = 20;
  226.     fwrite(&temp_char, sizeof(temp_char), 1, outfile);
  227.     temp_char = ((i+1) & 0xff00) >> 8;
  228.     fwrite(&temp_char, sizeof(temp_char), 1, outfile);
  229.     temp_char = ((i+1) & 0x00ff);
  230.     fwrite(&temp_char, sizeof(temp_char), 1, outfile);
  231.     offset += strlen(record[i]) + 1;
  232.   }
  233.  
  234.   fwrite(&pad, 2, 1, outfile);
  235.  
  236. /* write the special first record */
  237.   temp_long = LSwap(mode);
  238.   fwrite(&temp_long, sizeof(temp_long), 1, outfile);
  239.   temp_short = SSwap(last_used);
  240.   fwrite(&temp_short, sizeof(temp_short), 1, outfile);
  241.  
  242. /* write the text records */
  243.   for (i = 0; i < db_num_records - 1; i++) {
  244.     fwrite(record[i], strlen(record[i]) + 1, 1, outfile);
  245.   }
  246.  
  247.   fclose(outfile);
  248. }
  249. }
  250.  
  251. /****************************************************************************
  252. * FUNCTION:     get_records
  253. *
  254. * DESCRIPTION:  reads the text records from the input file into a buffer,
  255. *               transforming "\n" to the linefeed character (0x0a)
  256. ****************************************************************************/
  257. long get_records(void)
  258. {
  259. FILE *infile;
  260. int rec_count = 0;
  261. char buf[MAX_LINE_LENGTH];
  262.  
  263. infile = fopen(infile_name, "rt");
  264. if (infile) {
  265.   while (!feof(infile) && (rec_count < MAX_RECORDS)) {
  266.     memset(buf, 0, MAX_LINE_LENGTH);
  267.     fgets(buf, MAX_LINE_LENGTH, infile);
  268.     if (strlen(buf)) {
  269.       printf("processing record %d\n", rec_count + 1);
  270.       record[rec_count] = transform(buf);
  271.       rec_count++;
  272.     }
  273.   }
  274.   fclose(infile);
  275. }
  276. return(rec_count);
  277. }
  278.  
  279. /****************************************************************************
  280. * FUNCTION:     LSwap
  281. *
  282. * DESCRIPTION:  transforms an INTEL-architecture long int into a MOTOROLLA-
  283. *               architecture long int.
  284. ****************************************************************************/
  285. unsigned long LSwap(unsigned long l)
  286. {
  287. unsigned short temp_s1, temp_s2;
  288. unsigned long temp_l;
  289.  
  290. temp_s1 = SSwap((unsigned short)((l & 0xffff0000) >> 16));
  291. temp_s2 = SSwap((unsigned short)(l & 0x0000ffff));
  292. temp_l = ((unsigned long)temp_s2 << 16) + temp_s1;
  293. return(temp_l);
  294. }
  295.  
  296. /****************************************************************************
  297. * FUNCTION:     SSwap
  298. *
  299. * DESCRIPTION:  transforms an INTEL-architecture short int into a MOTOROLLA-
  300. *               architecture short int.
  301. ****************************************************************************/
  302. unsigned short SSwap(unsigned short s)
  303. {
  304. unsigned short temp;
  305.  
  306. temp = ((s & 0xff00) >> 8) + ((s & 0x00ff) << 8);
  307. return(temp);
  308. }
  309.  
  310. /****************************************************************************
  311. * FUNCTION:     transform
  312. *
  313. * DESCRIPTION:  transforms the passed string, converting "\n" to 0x0a (LF)
  314. ****************************************************************************/
  315. char *transform(char *s)
  316. {
  317. char *temp_buf;
  318. char *s1 = s, *s2;
  319. unsigned char escape = FALSE;
  320.  
  321. if (strlen(s) > 0) {
  322.   temp_buf = (char *)malloc(strlen(s) + 1);
  323.   memset(temp_buf, 0, strlen(s) + 1);
  324.   s2 = temp_buf;
  325.   while (*s1) {
  326.     if (*s1 == '\\') {
  327.       escape = TRUE;
  328.     }
  329.     else if (*s1 == LF) {
  330.     }
  331.     else {
  332.       if ((*s1 == 'n') && escape) {
  333.         *s2++ = LF;
  334.         escape = FALSE;
  335.       }
  336.       else
  337.         *s2++ = *s1;
  338.     }
  339.     s1++;
  340.   }
  341.   return(temp_buf);
  342. }
  343. }
  344.  
  345.